package com.zhoug.zmui.calendar;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.zhoug.common.adapters.recycler2.BaseRecyclerViewAdapter;
import com.zhoug.common.adapters.recycler2.BaseViewHolder;
import com.zhoug.common.utils.LogUtils;
import com.zhoug.common.utils.StringUtils;
import com.zhoug.common.utils.TimeUtils;
import com.zhoug.zmui.R;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;

/**
 * @Author: zhoug
 * @Date: 2024-01-26
 * @Description:
 */
public class ZMUICalendarView extends FrameLayout {
    private static final String TAG = ">>>ZMUICalendarView";
    private static boolean DEBUG = true;
    public static final int TAB_TYPE_TEXT = 0;//文字
    public static final int TAB_TYPE_IMAGE = 1;//图片

    private int mTabType = TAB_TYPE_TEXT;//下面的标签类型
    private OnCalendarListener mOnCalendarListener;//日历监听器
    private boolean mDayItemClickable = false;

    private DateFormat mDateFormat;
    private Adapter mDayAdapter;
    private Calendar mCalendar;
    private int mYear;//当前展示的日期的年
    private int mMonth;//当前展示的日期的月
    private int mMinYear;//最小年
    private int mMinMonth;//最小月
    private int mMaxYear;//最大年
    private int mMaxMonth;//最大月
    private CalendarDay mSelectDate;//选中的数据


    //属性
    private Attributes mAttributes;

    private CalendarRecyclerView mRecyclerView;
    private ViewGroup mCalendarWeek;
    private TextView mTvWeek1;
    private TextView mTvWeek2;
    private TextView mTvWeek3;
    private TextView mTvWeek4;
    private TextView mTvWeek5;
    private TextView mTvWeek6;
    private TextView mTvWeek7;
    private TextView mTvBgMonth;

    private ViewGroup mContainerDay;
    private ViewGroup mContainerCalendar;
    private ViewGroup mCalendarHeader;
    private ViewGroup mBtnLastMonth;
    private ImageView mIvLastMonth;
    private TextView mTvLastMonth;
    private ViewGroup mBtnNextMonth;
    private ImageView mIvNextMonth;
    private TextView mTvNextMonth;
    private TextView mTvDate;

    /**
     * 标记类型
     *
     * @param tabType {@link #TAB_TYPE_TEXT,#TAB_TYPE_IMAGE}
     */
    public void setTabType(int tabType) {
        this.mTabType = tabType;
    }

    public ZMUICalendarView(@NonNull Context context) {
        this(context, null);
    }

    public ZMUICalendarView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, R.attr.zmui_style_ZMUICalendarView);
    }

    public ZMUICalendarView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        if (DEBUG) {
            LogUtils.d(TAG, "init:");
        }
        View root = LayoutInflater.from(context).inflate(R.layout.zmui_calendar_view, this, false);
        addView(root);
        mCalendarWeek = findViewById(R.id.calendar_week);
        mRecyclerView = findViewById(R.id.recyclerView_calendar);
        mTvWeek1 = findViewById(R.id.tv_week1);
        mTvWeek2 = findViewById(R.id.tv_week2);
        mTvWeek3 = findViewById(R.id.tv_week3);
        mTvWeek4 = findViewById(R.id.tv_week4);
        mTvWeek5 = findViewById(R.id.tv_week5);
        mTvWeek6 = findViewById(R.id.tv_week6);
        mTvWeek7 = findViewById(R.id.tv_week7);
        mTvBgMonth = findViewById(R.id.tv_bg_month);
        mCalendarHeader = findViewById(R.id.calendar_header);
        mBtnLastMonth = findViewById(R.id.btn_lastMonth);
        mIvLastMonth = findViewById(R.id.iv_lastMonth);
        mTvLastMonth = findViewById(R.id.tv_lastMonth);
        mBtnNextMonth = findViewById(R.id.btn_nextMonth);
        mTvNextMonth = findViewById(R.id.tv_nextMonth);
        mIvNextMonth = findViewById(R.id.iv_nextMonth);
        mTvDate = findViewById(R.id.tv_date);
        mContainerDay = findViewById(R.id.container_day);
        mContainerCalendar = findViewById(R.id.container_calendar);

        int zmui_textColor = ContextCompat.getColor(context, R.color.zmui_textColor);
        float zmui_textSize = context.getResources().getDimension(R.dimen.zmui_textSize);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ZMUICalendarView, defStyleAttr, R.style.zmui_style_ZMUICalendarView);
        mAttributes = new Attributes();
        mAttributes.dayTextColor = a.getColor(R.styleable.ZMUICalendarView_zmui_dayTextColor, zmui_textColor);
        mAttributes.dayTextSize = a.getDimension(R.styleable.ZMUICalendarView_zmui_dayTextSize, zmui_textSize);
        mAttributes.dayTabColor = a.getColor(R.styleable.ZMUICalendarView_zmui_dayTabColor, zmui_textColor);
        mAttributes.dayTabSize = a.getDimension(R.styleable.ZMUICalendarView_zmui_dayTabSize, zmui_textSize);
        mAttributes.dayTabImageSize = a.getDimensionPixelSize(R.styleable.ZMUICalendarView_zmui_dayTabImageSize, 50);
        mAttributes.headerBackground = a.getDrawable(R.styleable.ZMUICalendarView_zmui_headerBackground);
        mAttributes.weekBackground = a.getDrawable(R.styleable.ZMUICalendarView_zmui_weekBackground);
        mAttributes.dateBackground = a.getDrawable(R.styleable.ZMUICalendarView_zmui_dateBackground);
        mAttributes.weekTextColor = a.getColor(R.styleable.ZMUICalendarView_zmui_weekTextColor, zmui_textColor);
        mAttributes.weekTextSize = a.getDimension(R.styleable.ZMUICalendarView_zmui_weekTextSize, zmui_textSize);
        mAttributes.weekTextStyle = a.getInt(R.styleable.ZMUICalendarView_zmui_weekTextStyle, Typeface.NORMAL);
        mAttributes.notCurrentMonthDayColor = a.getColor(R.styleable.ZMUICalendarView_zmui_notCurrentMonthDayColor, Color.parseColor("#bbbbbb"));
        mAttributes.showNotCurrentMonthDay = a.getBoolean(R.styleable.ZMUICalendarView_zmui_showNotCurrentMonthDay, true);
        mAttributes.showBgMonth = a.getBoolean(R.styleable.ZMUICalendarView_zmui_showBgMonth, true);
        mAttributes.lastBtnText = a.getString(R.styleable.ZMUICalendarView_zmui_lastBtnText);
        mAttributes.nextBtnText = a.getString(R.styleable.ZMUICalendarView_zmui_nextBtnText);
        mAttributes.lastBtnIcon = a.getDrawable(R.styleable.ZMUICalendarView_zmui_lastBtnIcon);
        mAttributes.nextBtnIcon = a.getDrawable(R.styleable.ZMUICalendarView_zmui_nextBtnIcon);
        mAttributes.showHeader = a.getBoolean(R.styleable.ZMUICalendarView_zmui_showHeader, true);
        mAttributes.headerTextColor = a.getColor(R.styleable.ZMUICalendarView_zmui_headerTextColor, zmui_textColor);
        mAttributes.headerTextSize = a.getDimension(R.styleable.ZMUICalendarView_zmui_headerTextSize, zmui_textSize);
        mAttributes.headerTextStyle = a.getInt(R.styleable.ZMUICalendarView_zmui_headerTextStyle, Typeface.BOLD);
        mAttributes.btnTextColor = a.getColor(R.styleable.ZMUICalendarView_zmui_btnTextColor, zmui_textColor);
        mAttributes.btnTextSize = a.getDimension(R.styleable.ZMUICalendarView_zmui_btnTextSize, zmui_textSize);
        mAttributes.btnTextStyle = a.getInt(R.styleable.ZMUICalendarView_zmui_btnTextStyle, Typeface.NORMAL);
        mAttributes.btnImageTint = a.getColor(R.styleable.ZMUICalendarView_zmui_btnImageTint, 0);
        mAttributes.daySelectEnabled = a.getBoolean(R.styleable.ZMUICalendarView_zmui_daySelectEnabled, false);
        mAttributes.supportCancelSelected = a.getBoolean(R.styleable.ZMUICalendarView_zmui_supportCancelSelected, false);
        mAttributes.hideDateEnable = a.getBoolean(R.styleable.ZMUICalendarView_zmui_hideDateEnable, false);
        mAttributes.dayTabBackground = a.getDrawable(R.styleable.ZMUICalendarView_zmui_dayTabBackground);

        a.recycle();
        initAttrs();

        mCalendar = Calendar.getInstance();
        mCalendar.setTimeInMillis(System.currentTimeMillis());
        mDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        mDayAdapter = new Adapter();
        mDayAdapter.setData(new ArrayList<>());
        mRecyclerView.setAdapter(mDayAdapter);
        mRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 7));
        mRecyclerView.setOnTouchPositionListener(new CalendarRecyclerView.OnTouchPositionListener() {
            @Override
            public void onOpen(int position) {
                if (DEBUG) {
                    LogUtils.d(TAG, "onOpen:" + position);
                }
                CalendarDay itemData = mDayAdapter.getItemData(position);
                if (mOnCalendarListener != null) {
                    if (itemData != null) {
                        mOnCalendarListener.OnTouchDownPosition(itemData, position);
                    } else {
                        mOnCalendarListener.OnTouchDownPosition(null, position);
                    }
                }
            }

            @Override
            public void onMoveChange(int position) {
                if (DEBUG) {
                    LogUtils.d(TAG, "onMoveChange:" + position);
                }
                CalendarDay itemData = mDayAdapter.getItemData(position);
                if (mOnCalendarListener != null) {
                    if (itemData != null) {
                        mOnCalendarListener.OnTouchMovePosition(itemData, position);
                    } else {
                        mOnCalendarListener.OnTouchMovePosition(null, position);
                    }
                }
            }

            @Override
            public void onClose(int position) {
                if (DEBUG) {
                    LogUtils.d(TAG, "onClose:" + position);
                }
                CalendarDay itemData = mDayAdapter.getItemData(position);
                if (mOnCalendarListener != null) {
                    if (itemData != null) {
                        mOnCalendarListener.OnTouchUpPosition(itemData, position);
                    } else {
                        mOnCalendarListener.OnTouchUpPosition(null, position);
                    }
                }
            }
        });
        mBtnLastMonth.setOnClickListener(v -> {
            //前一月
            int month = mMonth;
            int year = mYear;
            month--;
            if (month <= 0) {
                month = 12;
                year--;
            }
            setDate(year, month);
        });
        mBtnNextMonth.setOnClickListener(v -> {
            //后一月
            int month = mMonth;
            int year = mYear;
            month++;
            if (month > 12) {
                month = 1;
                year++;
            }
            setDate(year, month);
        });
        mTvDate.setOnClickListener(v -> {
            if (mAttributes.hideDateEnable) {
                int visibility = mContainerCalendar.getVisibility();
                if (visibility == View.VISIBLE) {
                    mContainerCalendar.setVisibility(GONE);
                } else {
                    mContainerCalendar.setVisibility(VISIBLE);
                }
                setHeaderTitle();
            }

        });

        setDate(mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH) + 1);

    }

    /**
     * 初始化属性
     */
    private void initAttrs() {
        mCalendarHeader.setBackground(mAttributes.headerBackground);
        mContainerDay.setBackground(mAttributes.dateBackground);
        mTvDate.setTextColor(mAttributes.headerTextColor);
        mTvDate.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.headerTextSize);
        mTvDate.setTypeface(Typeface.defaultFromStyle(mAttributes.headerTextStyle));
        setWeekStyle();
        mTvLastMonth.setTextColor(mAttributes.btnTextColor);
        mTvLastMonth.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.btnTextSize);
        mTvLastMonth.setTypeface(Typeface.defaultFromStyle(mAttributes.btnTextStyle));
        mTvNextMonth.setTextColor(mAttributes.btnTextColor);
        mTvNextMonth.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.btnTextSize);
        mTvNextMonth.setTypeface(Typeface.defaultFromStyle(mAttributes.btnTextStyle));
        mTvBgMonth.setVisibility(mAttributes.showBgMonth ? VISIBLE : GONE);
        if (mAttributes.lastBtnText != null) {
            mTvLastMonth.setText(mAttributes.lastBtnText);
        }
        if (mAttributes.nextBtnText != null) {
            mTvNextMonth.setText(mAttributes.nextBtnText);
        }
        if (mAttributes.lastBtnIcon != null) {
            mIvLastMonth.setVisibility(VISIBLE);
            mIvLastMonth.setImageDrawable(mAttributes.lastBtnIcon);
            if (mAttributes.btnImageTint != 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mIvLastMonth.setImageTintList(ColorStateList.valueOf(mAttributes.btnImageTint));
            }
        } else {
            mIvLastMonth.setVisibility(INVISIBLE);
        }
        if (mAttributes.nextBtnIcon != null) {
            mIvNextMonth.setVisibility(VISIBLE);
            mIvNextMonth.setImageDrawable(mAttributes.nextBtnIcon);
            if (mAttributes.btnImageTint != 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mIvNextMonth.setImageTintList(ColorStateList.valueOf(mAttributes.btnImageTint));
            }
        } else {
            mIvNextMonth.setVisibility(INVISIBLE);
        }

        mCalendarHeader.setVisibility(mAttributes.showHeader ? VISIBLE : GONE);
    }


    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (DEBUG) {
            LogUtils.d(TAG, "onFinishInflate:");
        }

    }

    private boolean isSelected(CalendarDay day) {
        return mSelectDate != null && Objects.equals(mSelectDate.getDate(), day.getDate());
    }

    private class Adapter extends BaseRecyclerViewAdapter<CalendarDay> implements OnClickListener {

        @Override
        public int getLayoutId(int viewType) {
            return R.layout.zmui_calendar_day_view;
        }

        @NonNull
        @Override
        public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            BaseViewHolder baseViewHolder = super.onCreateViewHolder(parent, viewType);
            ImageView image_tab = baseViewHolder.getView(R.id.image_tab);
            if (mAttributes.dayTabImageSize > 0) {
                ViewGroup.LayoutParams layoutParams = image_tab.getLayoutParams();
                if (layoutParams != null) {
                    layoutParams.width = mAttributes.dayTabImageSize;
                    layoutParams.height = mAttributes.dayTabImageSize;
                    image_tab.setLayoutParams(layoutParams);
                }
            }
            return baseViewHolder;
        }

        @Override
        public void onBindData(BaseViewHolder holder, CalendarDay data, int position, int viewType) {
            if (data != null) {
                TextView textDay = holder.getView(R.id.text_day);
                TextView textTab = holder.getView(R.id.text_tab);
                ImageView imageTab = holder.getView(R.id.image_tab);
                textDay.setText(String.valueOf(data.getDay()));
                textDay.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.dayTextSize);
                textTab.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.dayTabSize);
                TagData tagData = data.getTagData();
                if (data.isCurrentMonth()) {
                    textDay.setVisibility(VISIBLE);
                    textDay.setTextColor(mAttributes.dayTextColor);
                } else {
                    if (mAttributes.showNotCurrentMonthDay) {
                        textDay.setVisibility(VISIBLE);
                    } else {
                        textDay.setVisibility(INVISIBLE);
                    }
                    holder.itemView.setBackground(null);
                    textDay.setTextColor(mAttributes.notCurrentMonthDayColor);
                    textTab.setText(null);
                    imageTab.setImageDrawable(null);
                }

                if (tagData != null) {
                    textTab.setVisibility(VISIBLE);
                    if (tagData.getBackground() == null) {
                        holder.itemView.setBackground(mAttributes.dayTabBackground);
                    } else {
                        holder.itemView.setBackground(tagData.getBackground());
                    }

                    textTab.setText(tagData.getTabText());
                    if (tagData.getTabTextColor() != 0) {
                        textTab.setTextColor(tagData.getTabTextColor());
                    } else {
                        textTab.setTextColor(mAttributes.dayTabColor);
                    }
                    if (tagData.getTabIcon() != 0) {
                        imageTab.setImageResource(tagData.getTabIcon());
                    } else {
                        imageTab.setImageDrawable(null);
                    }
                    holder.itemView.setSelected(isSelected(data));

                } else {
                    holder.itemView.setBackground(null);
                    textTab.setText(null);
                    imageTab.setImageDrawable(null);
                }

                if (mTabType == TAB_TYPE_IMAGE) {
                    textTab.setVisibility(GONE);
                    if (tagData != null) {
                        imageTab.setVisibility(VISIBLE);
                    } else {
                        imageTab.setVisibility(INVISIBLE);
                    }
                } else {
                    imageTab.setVisibility(GONE);
                    if (tagData != null) {
                        textTab.setVisibility(VISIBLE);
                    } else {
                        textTab.setVisibility(INVISIBLE);
                    }
                }

                holder.itemView.setOnClickListener(this);
                holder.itemView.setClickable(true);
                holder.itemView.setTag(position);


            }
        }

        @Override
        public void onClick(View v) {
            int position = (int) v.getTag();
            CalendarDay day = getItemData(position);
            if (mAttributes.daySelectEnabled) {
                boolean selected = isSelected(day);
                //已经选中
                if (selected) {
                    //支持取消选中
                    if (mAttributes.supportCancelSelected) {
                        mSelectDate = null;
                        if (mOnCalendarListener != null) {
                            mOnCalendarListener.onCancelSelected(day);
                        }
                        notifyDataSetChanged1();
                    }
                } else {
                    //未选中-选中
                    mSelectDate = day;
                    if (mOnCalendarListener != null) {
                        mOnCalendarListener.onSelectedChange(day);
                    }
                    notifyDataSetChanged1();
                }
            }
            if (mDayItemClickable && mOnCalendarListener != null) {
                mOnCalendarListener.onDayItemClick(day, position);
            }
        }
    }


    /**
     * 设置日期栏样式
     */
    private void setWeekStyle() {
        mCalendarWeek.setBackground(mAttributes.weekBackground);
        mTvWeek1.setTextColor(mAttributes.weekTextColor);
        mTvWeek1.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.weekTextSize);
        mTvWeek1.setTypeface(Typeface.defaultFromStyle(mAttributes.weekTextStyle));
        mTvWeek2.setTextColor(mAttributes.weekTextColor);
        mTvWeek2.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.weekTextSize);
        mTvWeek2.setTypeface(Typeface.defaultFromStyle(mAttributes.weekTextStyle));
        mTvWeek3.setTextColor(mAttributes.weekTextColor);
        mTvWeek3.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.weekTextSize);
        mTvWeek3.setTypeface(Typeface.defaultFromStyle(mAttributes.weekTextStyle));
        mTvWeek4.setTextColor(mAttributes.weekTextColor);
        mTvWeek4.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.weekTextSize);
        mTvWeek4.setTypeface(Typeface.defaultFromStyle(mAttributes.weekTextStyle));
        mTvWeek5.setTextColor(mAttributes.weekTextColor);
        mTvWeek5.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.weekTextSize);
        mTvWeek5.setTypeface(Typeface.defaultFromStyle(mAttributes.weekTextStyle));
        mTvWeek6.setTextColor(mAttributes.weekTextColor);
        mTvWeek6.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.weekTextSize);
        mTvWeek6.setTypeface(Typeface.defaultFromStyle(mAttributes.weekTextStyle));
        mTvWeek7.setTextColor(mAttributes.weekTextColor);
        mTvWeek7.setTextSize(TypedValue.COMPLEX_UNIT_PX, mAttributes.weekTextSize);
        mTvWeek7.setTypeface(Typeface.defaultFromStyle(mAttributes.weekTextStyle));
    }


    /**
     * 设置日期标题日期
     */
    private void setHeaderTitle() {
        boolean visibility = mContainerCalendar.getVisibility() == VISIBLE;
        CharSequence title = null;
        if (mOnCalendarListener != null) {
            title = mOnCalendarListener.getCalendarHeaderTitle(visibility, mYear, mMonth, mSelectDate);
        }
        if (title != null) {
            mTvDate.setText(title);
        } else {
            if (!visibility && mSelectDate != null) {
                String day = mSelectDate.getDate().split("-")[2];
                if (day.startsWith("0")) {
                    day = day.substring(1);
                }
                mTvDate.setText(StringUtils.format("%d年%d月%d日", mYear, mMonth, day));
            } else {
                mTvDate.setText(StringUtils.format("%d年%d月", mYear, mMonth));
            }
        }

    }


    private int getWeek(Calendar calendar) {
        int week = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        if (week == 0) {
            week = 7;
        }
        return week;
    }


    /**
     * 判断是否显示上一月
     */
    private void showLastBtn() {
        if (mMinYear > 0 && mMinMonth > 0) {
            if (mYear <= mMinYear) {
                if (mMonth <= mMinMonth) {
                    mBtnLastMonth.setVisibility(INVISIBLE);
                } else {
                    mBtnLastMonth.setVisibility(VISIBLE);
                }
            } else {
                mBtnLastMonth.setVisibility(VISIBLE);
            }
        } else {
            mBtnLastMonth.setVisibility(VISIBLE);

        }
    }

    /**
     * 判断是否显示下一月
     */
    private void showNextBtn() {
        if (mMaxYear > 0 && mMaxMonth > 0) {
            if (mYear >= mMaxYear) {
                if (mMonth > mMaxMonth) {
                    mBtnNextMonth.setVisibility(INVISIBLE);
                } else {
                    mBtnNextMonth.setVisibility(VISIBLE);
                }
            } else {
                mBtnNextMonth.setVisibility(VISIBLE);
            }
        } else {
            mBtnNextMonth.setVisibility(VISIBLE);

        }
    }

    /**
     * 静止切换月的按钮点击
     */
    public void hideMonthBtn() {
        mBtnNextMonth.setVisibility(INVISIBLE);
        mBtnLastMonth.setVisibility(INVISIBLE);
    }

    public void showMonthBtn() {
        showNextBtn();
        showLastBtn();
    }


    private static class Attributes {
        private int dayTextColor;//日文字颜色
        private float dayTextSize;//日文字大小
        private int dayTabColor;//日下面的标签文字颜色
        private float dayTabSize;//日下面的标签文字大小
        private int dayTabImageSize;//日下面的标签图片大小
        private Drawable headerBackground;//日历头部背景
        private Drawable weekBackground;//日历星期栏背景
        private Drawable dateBackground;//日历日期背景
        private int weekTextColor;//星期文字颜色
        private float weekTextSize;//星期文字大小
        private int weekTextStyle;//星期文字样式
        private int notCurrentMonthDayColor;   //非本月日期颜色
        private boolean showNotCurrentMonthDay;   //非本月日期是否显示
        private boolean showBgMonth;//是否显示背景月
        private String lastBtnText;//上一月文字
        private String nextBtnText;//下一月文字
        private Drawable lastBtnIcon;//上一月图标
        private Drawable nextBtnIcon;//下一月图标
        private boolean showHeader;//是否显示日期头
        private int headerTextColor;//日期头文字颜色
        private float headerTextSize;//日期头文字大小
        private int headerTextStyle;//日期头文字样式
        private int btnTextColor;//日期头上月/下月按钮文字颜色
        private float btnTextSize;//日期头上月/下月按钮文字大小
        private int btnTextStyle;//日期头上月/下月按钮文字样式
        private int btnImageTint;//日期头上月/下月按钮图片Tint
        private boolean daySelectEnabled;//日期是否可以点击选中
        private boolean supportCancelSelected;//日期选中是否支持取消
        private boolean hideDateEnable;//点击日历头上的日期隐藏日期内容
        private Drawable dayTabBackground;//标签数据默认背景


    }


    /**
     * 各位数添加0
     *
     * @param num 2
     * @return 02
     */
    private static String addZero(String num) {
        if (num != null && num.length() == 1) {
            return "0" + num;
        }
        return num;
    }

    /**
     * 各位数添加0
     *
     * @param num 2
     * @return 02
     */
    private static String addZero(int num) {
        return addZero(String.valueOf(num));
    }


    /**
     * 设置日期
     *
     * @param year
     * @param month
     */
    public void setDate(int year, int month) {
        if (DEBUG) {
            LogUtils.d(TAG, "setDate:" + year + "年" + month + "月");
        }
        if (this.mYear != year || this.mMonth != month) {
            this.mYear = year;
            this.mMonth = month;
            List<CalendarDay> listDay = new ArrayList<>();
            mCalendar.clear();
            mCalendar.set(Calendar.YEAR, mYear);
            mCalendar.set(Calendar.MONTH, mMonth - 1);
            mCalendar.set(Calendar.DAY_OF_MONTH, 1);
            //本月最后一天
            int lastDay = TimeUtils.getLastDay(mYear, mMonth);
            //本月第一天是星期几
            int startWeek = getWeek(mCalendar);
            mCalendar.set(Calendar.DAY_OF_MONTH, lastDay);
            //本月最后一天是星期几
            int endWeek = getWeek(mCalendar);
            //日一二...六
            //前面补多少天
            int startAdd = startWeek == 7 ? 0 : startWeek;
            //后面补多少天
            int endAdd = endWeek == 7 ? 6 : 6 - endWeek;
            int dayNum = startAdd + endAdd + lastDay;
            mCalendar.set(Calendar.DAY_OF_MONTH, 1);
            mCalendar.add(Calendar.DAY_OF_YEAR, -startAdd);
            for (int i = 0; i < dayNum; i++) {
                int y = mCalendar.get(Calendar.YEAR);
                int m = mCalendar.get(Calendar.MONTH);
                if (y == year && m == month - 1) {
                    listDay.add(new CalendarDay(mDateFormat.format(mCalendar.getTime()), true));
                } else {
                    listDay.add(new CalendarDay(mDateFormat.format(mCalendar.getTime()), false));
                }
                mCalendar.add(Calendar.DAY_OF_YEAR, 1);
            }

            setHeaderTitle();
            showNextBtn();
            showLastBtn();
            if (mAttributes.showBgMonth) {
                mTvBgMonth.setText(String.valueOf(mMonth));
            }

            setSelect(null);
            setCalendarDay(null);
            mDayAdapter.loadSuccess(listDay);
            if (mOnCalendarListener != null) {
                mOnCalendarListener.onCalendarChange(mYear, mMonth);
            }
        }
    }

    /**
     * 设置选中的CalendarDay 需要在 {@link #setCalendarDay(List)}之前调用 否则需要调用{@link #notifyDataSetChanged()}刷新
     *
     * @param tagData
     */
    public void setSelect(TagData tagData) {
        if (tagData != null) {
            this.mSelectDate = getDay(tagData.getDate());
            setHeaderTitle();
        }

    }

    /**
     * 设置标记数据
     *
     * @param tags
     */
    public void setCalendarDay(List<TagData> tags) {
        List<CalendarDay> days = mDayAdapter.getData();
        if (days.size() > 0) {
            TagData find;
            for (CalendarDay day : days) {
                find = null;
                if (tags != null && tags.size() > 0) {
                    for (TagData tagData : tags) {
                        if (tagData != null && Objects.equals(tagData.getDate(), day.getDate())) {
                            find = tagData;
                            break;
                        }
                    }
                }
                day.setTagData(find);
            }
        }
        mDayAdapter.notifyDataSetChanged1();
    }

    /**
     * 添加标记数据
     *
     * @param tags
     */
    public void addCalendarDays(List<TagData> tags) {
        List<CalendarDay> days = mDayAdapter.getData();
        if (days.size() > 0) {
            TagData find;
            for (CalendarDay day : days) {
                find = null;
                if (tags != null && tags.size() > 0) {
                    for (TagData tagData : tags) {
                        if (tagData != null && Objects.equals(tagData.getDate(), day.getDate())) {
                            find = tagData;
                            break;
                        }
                    }
                }
                if (find != null) {
                    day.setTagData(find);
                }
            }
        }
        mDayAdapter.notifyDataSetChanged1();
    }


    /**
     * 添加标记数据
     *
     * @param tagData
     */
    public void addCalendarDay(@NonNull TagData tagData) {
        CalendarDay day = getDay(tagData.getDate());
        if (day != null) {
            day.setTagData(tagData);
        }
        mDayAdapter.notifyDataSetChanged1();
    }

    /**
     * 移除标记数据
     *
     * @param data
     */
    public void removeCalendarDay(@NonNull TagData data) {
        removeCalendarDay(data.getDate());
    }

    public void removeCalendarDay(@NonNull CalendarDay calendarDay) {
        calendarDay.setTagData(null);
    }

    /**
     * 移除标记数据
     *
     * @param date
     */
    public void removeCalendarDay(@NonNull String date) {
        CalendarDay day = getDay(date);
        if (day != null) {
            day.setTagData(null);
        }
        mDayAdapter.notifyDataSetChanged1();
    }


    /**
     * 获取日历标记数据
     *
     * @return
     */
    public List<TagData> getTagData() {
        List<TagData> list = null;
        List<CalendarDay> days = mDayAdapter.getData();
        if (days.size() > 0) {
            list = new ArrayList<>();
            for (CalendarDay day : days) {
                TagData tagData = day.getTagData();
                if (tagData != null) {
                    list.add(tagData);
                }
            }
        }
        return list;
    }

    /**
     * 获取日历标记日期 格式 yyyy-mm-dd
     *
     * @return
     */
    public List<String> getTabDate() {
        List<String> list = null;
        List<CalendarDay> days = mDayAdapter.getData();
        if (days.size() > 0) {
            list = new ArrayList<>();
            for (CalendarDay day : days) {
                TagData tagData = day.getTagData();
                if (tagData != null) {
                    list.add(tagData.getDate());
                }
            }
        }
        return list;
    }

    public CalendarDay getDay(String date) {
        if (date != null) {
            List<CalendarDay> days = mDayAdapter.getData();
            if (days.size() > 0) {
                for (CalendarDay item : days) {
                    if (Objects.equals(item.getDate(), date)) {
                        return item;
                    }
                }
            }
        }
        return null;
    }


    public List<CalendarDay> getDays(){
        return mDayAdapter.getData();
    }

    public int getDayCount(){
        return mDayAdapter.getItemCount();
    }

    public CalendarDay getDay(int position) {
        return mDayAdapter.getItemData(position);
    }


    /**
     * 刷新数据
     */
    public void notifyDataSetChanged() {
        mDayAdapter.notifyDataSetChanged1();
    }

    /**
     * 刷新数据
     */
    public void notifyItemChanged(int position) {
        mDayAdapter.notifyItemChanged(position);
    }

    public void setMinDate(int minYear, int minMonth) {
        this.mMinYear = minYear;
        this.mMinMonth = minMonth;
        showLastBtn();
    }

    public void setMaxDate(int maxYear, int maxMonth) {
        this.mMaxYear = maxYear;
        this.mMaxMonth = maxMonth;
        showNextBtn();
    }


    /**
     * 当前展示的日期的年
     *
     * @return
     */
    public int getYear() {
        return mYear;
    }

    /**
     * 当前展示的日期的月
     *
     * @return
     */
    public int getMonth() {
        return mMonth;
    }

    /**
     * 获取年月 eg:2024-05
     *
     * @return
     */
    public String getYearMonth() {
        return mYear + "-" + addZero(mMonth);
    }

    /**
     * 获取选中的
     *
     * @return
     */
    public CalendarDay getSelect() {
        return mSelectDate;
    }


    /**
     * 设置是否可以点击日
     *
     * @param dayItemClickable
     */
    public void setDayItemClickable(boolean dayItemClickable) {
        this.mDayItemClickable = dayItemClickable;
    }

    /**
     * 长按启动连续选择tag功能
     *
     * @param longTouchSelectable
     */
    public void setLongTouchSelectable(boolean longTouchSelectable) {
        mRecyclerView.setTouchPositionEnable(longTouchSelectable);

    }

    /**
     * 日期监听器
     *
     * @param onCalendarListener
     */
    public void setOnCalendarListener(OnCalendarListener onCalendarListener) {
        this.mOnCalendarListener = onCalendarListener;
    }


}
